package net.lab1024.sa.admin.common;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import lombok.AllArgsConstructor;
import lombok.Data;
import net.lab1024.sa.admin.constant.SynthesisConst;
import net.lab1024.sa.admin.module.business.category.domain.dto.UserImportDTO;
import net.lab1024.sa.admin.module.business.category.domain.entity.RoleUser;
import net.lab1024.sa.admin.module.business.category.domain.entity.User;
import net.lab1024.sa.admin.module.business.category.service.UserService;
import net.lab1024.sa.admin.module.system.role.service.RoleService;
import net.lab1024.sa.admin.module.system.role.service.RoleUserService;
import net.lab1024.sa.base.module.support.apiencrypt.service.ApiEncryptService;
import net.lab1024.sa.base.module.support.securityprotect.service.SecurityPasswordService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.*;
import java.util.stream.Collectors;

public class UserImportListener extends AnalysisEventListener<UserImportDTO> {

    private static final Logger logger = LoggerFactory.getLogger(UserImportListener.class);

    //计数器
    private int processedCount = 0;
    private static final int BATCH_SIZE = 100;
    private final UserService userService;
    private final RoleUserService roleUserService;
    private final RoleService roleService;
    private final TransactionTemplate transactionTemplate;
    private final String creator;
    private ApiEncryptService apiEncryptService;

    private List<UserImportDTO> cachedDTOList = new ArrayList<>();
    private final List<ImportResult> errorList = new ArrayList<>();
    private final List<UserImportDTO> allDataList = new ArrayList<>();
    //private final List<ImportResult> validationErrors = new ArrayList<>();

    private final Set<String> batchUserCodes = new HashSet<>(); // 批次内学号缓存

    public UserImportListener(UserService userService,
                              RoleUserService roleUserService,
                              RoleService roleService,
                              TransactionTemplate transactionTemplate,
                              ApiEncryptService apiEncryptService,
                              String creator) {
        this.userService = userService;
        this.roleUserService = roleUserService;
        this.roleService = roleService;
        this.transactionTemplate = transactionTemplate;
        this.apiEncryptService = apiEncryptService;
        this.creator = creator;
    }

    @Override
    public void invoke(UserImportDTO data, AnalysisContext context) {
        //        processedCount++;
        //        try {
        //            validateUser(data);
        //            cachedDTOList.add(data);
        //            if (cachedDTOList.size() >= BATCH_SIZE) {
        //                saveData();
        //                cachedDTOList = new ArrayList<>();
        //            }
        //        } catch (Exception e) {
        //            errorList.add(new ImportResult(context.readRowHolder().getRowIndex(), e.getMessage()));
        //        }

        // processedCount++;
        // ValidationResult validationResult = validateUser(data, context.readRowHolder().getRowIndex());
        // if (!validationResult.isValid()) {
        //     errorList.add(new ImportResult(context.readRowHolder().getRowIndex(), validationResult.getErrorMessage()));
        //     return;
        // }
        // cachedDTOList.add(data);
        // batchUserCodes.add(data.getUserCode()); // 添加到批次学号缓存
        // if (cachedDTOList.size() >= BATCH_SIZE) {
        //     saveData();
        //     cachedDTOList = new ArrayList<>();
        //     batchUserCodes.clear();
        // }

        processedCount++;
        int rowNum = context.readRowHolder().getRowIndex() + 1; // Excel行号(从1开始)

        // 只进行数据收集，不立即校验
        allDataList.add(data);

    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // if (!cachedDTOList.isEmpty()) {
        //     saveData();
        //     batchUserCodes.clear();
        // }

        // 1. 检查数据重复性（在本次导入文件中）
        checkDuplicates();

        // 2. 执行完整校验
        validateAllData();

        // 3. 如果校验通过，执行导入
        if (errorList.isEmpty()) {
            saveAllData();
        }
    }

    private void saveAllData() {
        transactionTemplate.execute(status -> {
            try {
                // 1. 转换DTO为User实体
                List<User> users = allDataList.stream()
                        .map(this::convertToUser)
                        .collect(Collectors.toList());

                // 2. 批量保存用户
                userService.saveBatch(users);

                // 3. 构建用户学号->用户ID映射
                Map<String, Long> userCodeIdMap = users.stream()
                        .collect(Collectors.toMap(User::getUserCode, User::getId));

                // 4. 构建角色关联关系
                List<RoleUser> roleUsers = new ArrayList<>();
                for (UserImportDTO dto : allDataList) {
                    Long userId = userCodeIdMap.get(dto.getUserCode());
                    if (userId != null) {
                        Integer roleId = convertRole(dto.getRoleStr());
                        if (roleId != null) {
                            roleUsers.add(createRoleUser(roleId.longValue(), userId));
                        }
                    }
                }

                // 5. 批量保存角色关联
                if (!roleUsers.isEmpty()) {
                    roleUserService.saveBatch(roleUsers);
                }
                return true;
            } catch (Exception e) {
                status.setRollbackOnly();
                logger.error("导入用户事务失败", e);
                // 将系统错误添加到错误列表
                errorList.add(new ImportResult(-1, "系统错误: " + e.getMessage()));
                return false;
            }
        });
    }

    private void checkDuplicates() {
        Map<String, List<Integer>> userCodeMap = new HashMap<>();

        for (int i = 0; i < allDataList.size(); i++) {
            UserImportDTO dto = allDataList.get(i);
            int rowNum = i + 1; // 行号从1开始

            if (StringUtils.isNotBlank(dto.getUserCode())) {
                userCodeMap.computeIfAbsent(dto.getUserCode(), k -> new ArrayList<>())
                        .add(rowNum);
            }
        }

        // 找出重复的学工号
        userCodeMap.forEach((userCode, rowNums) -> {
            if (rowNums.size() > 1) {
                String errorMsg = String.format("学工号重复: %s (出现在行: %s)",
                        userCode, rowNums.stream().map(Object::toString).collect(Collectors.joining(",")));

                // 为每个重复的行添加错误
                rowNums.forEach(row -> {
                    errorList.add(new ImportResult(row, errorMsg));
                });
            }
        });
    }

    private void validateAllData() {
        // 如果已经发现重复错误，跳过其他校验
        if (!errorList.isEmpty()) return;

        // 检查数据库中的重复学工号
        Set<String> existingUserCodes = getExistingUserCodes();

        for (int i = 0; i < allDataList.size(); i++) {
            UserImportDTO dto = allDataList.get(i);
            int rowNum = i + 1; // 行号从1开始

            ValidationResult result = validateUser(dto, existingUserCodes);

            if (!result.isValid()) {
                errorList.add(new ImportResult(rowNum, result.getErrorMessage()));
            }
        }
    }

    private Set<String> getExistingUserCodes() {
        // 提取所有学工号
        Set<String> userCodes = allDataList.stream()
                .map(UserImportDTO::getUserCode)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toSet());

        if (userCodes.isEmpty()) {
            return Collections.emptySet();
        }

        // 查询数据库中已存在的学工号
        return userService.lambdaQuery()
                .select(User::getUserCode)
                .in(User::getUserCode, userCodes)
                .list()
                .stream()
                .map(User::getUserCode)
                .collect(Collectors.toSet());
    }

    private ValidationResult validateUser(UserImportDTO dto, int rowIndex) {
        ValidationResult result = new ValidationResult();

        // 1. 基础字段非空校验
        if (StringUtils.isBlank(dto.getName())) {
            result.addError("姓名不能为空");
        }
        //if (StringUtils.isBlank(dto.getSex())) {
        //    result.addError("性别不能为空");
        //}
        if (StringUtils.isBlank(dto.getUserCode())) {
            result.addError("学工号不能为空");
        }
        if (StringUtils.isBlank(dto.getRoleStr())) {
            result.addError("角色不能为空");
        }
        if (StringUtils.isBlank(dto.getPositionStr())) {
            result.addError("职务不能为空");
        }
        if (StringUtils.isBlank(dto.getCollegeStr())) {
            result.addError("学院不能为空");
        }
        if (StringUtils.isBlank(dto.getClassName())) {
            result.addError("班级不能为空");
        }

        // 2. 格式校验
        if (dto.getPhone() != null && !dto.getPhone().matches("^1[3-9]\\d{9}$")) {
            result.addError("手机号格式不正确");
        }
        if (dto.getEmail() != null && !dto.getEmail().matches("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$")) {
            result.addError("邮箱格式不正确");
        }

        // 3. 业务逻辑校验
        if (result.isValid()) {
            // 性别校验
            // if (!EnumConverter.CLASS_MAP.keySet().contains(dto.getSex())) {
            //     result.addError("无效的性别名称: " + dto.getCollegeStr());
            // }

            // 班级校验
            if (!EnumConverter.CLASS_MAP.keySet().contains(dto.getCollegeStr())) {
                result.addError("无效的班级名称: " + dto.getCollegeStr());
            }

            // 职务校验
            if (!EnumConverter.POSITION_MAP.keySet().contains(dto.getPositionStr())) {
                result.addError("无效的职务类型: " + dto.getPositionStr());
            }

            // 角色校验
            if (!EnumConverter.ROLE_MAP.keySet().contains(dto.getRoleStr())) {
                result.addError("无效的角色类型: " + dto.getRoleStr());
            }

            // 学院校验
            if (!EnumConverter.COLLEGE_MAP.keySet().contains(dto.getCollegeStr())) {
                result.addError("无效的学院名称: " + dto.getCollegeStr());
            }

            // 学号批次内重复检查
            if (batchUserCodes.contains(dto.getUserCode())) {
                result.addError("学工号在本批次中重复: " + dto.getUserCode());
            }

            // 学号全局重复检查（在事务外预检查）
            if (userService.lambdaQuery()
                    .eq(User::getUserCode, dto.getUserCode())
                    .exists()) {
                result.addError("学工号已存在: " + dto.getUserCode());
            }
        }

        return result;
    }

    private ValidationResult validateUser(UserImportDTO dto, Set<String> existingUserCodes) {
        ValidationResult result = new ValidationResult();

        // 1. 基础字段非空校验
        if (StringUtils.isBlank(dto.getName())) {
            result.addError("姓名不能为空");
        }
        if (StringUtils.isBlank(dto.getGenderStr())) {
            result.addError("性别不能为空");
        }
        if (StringUtils.isBlank(dto.getUserCode())) {
            result.addError("学工号不能为空");
        }
        if (StringUtils.isBlank(dto.getRoleStr())) {
            result.addError("角色不能为空");
        }
        if (StringUtils.isBlank(dto.getPositionStr())) {
            result.addError("职务不能为空");
        }
        if (StringUtils.isBlank(dto.getCollegeStr())) {
            result.addError("学院不能为空");
        }
        if (StringUtils.isBlank(dto.getClassName())) {
            result.addError("班级不能为空");
        }

        // 2. 格式校验
        if (StringUtils.isNotBlank(dto.getPhone()) && !dto.getPhone().matches("^1[3-9]\\d{9}$")) {
            result.addError("手机号格式不正确");
        }
        if (StringUtils.isNotBlank(dto.getEmail()) && !dto.getEmail().matches("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$")) {
            result.addError("邮箱格式不正确");
        }

        // 3. 业务逻辑校验
        if (result.isValid()) {
            // 班级校验
            if (!EnumConverter.CLASS_MAP.keySet().contains(dto.getClassName())) {
                result.addError("无效的班级名称: " + dto.getClassName());
            }

            // 性别校验
            if (!EnumConverter.SEX_MAP.keySet().contains(dto.getGenderStr())) {
                result.addError("无效的性别类型: " + dto.getGenderStr());
            }

            // 职务校验
            if (!EnumConverter.POSITION_MAP.keySet().contains(dto.getPositionStr())) {
                result.addError("无效的职务类型: " + dto.getPositionStr());
            }

            // 角色校验
            if (!EnumConverter.ROLE_MAP.keySet().contains(dto.getRoleStr())) {
                result.addError("无效的角色类型: " + dto.getRoleStr());
            }

            // 学院校验
            if (!EnumConverter.COLLEGE_MAP.keySet().contains(dto.getCollegeStr())) {
                result.addError("无效的学院名称: " + dto.getCollegeStr());
            }

            // 学号批次内重复检查
            if (batchUserCodes.contains(dto.getUserCode())) {
                result.addError("学工号在本批次中重复: " + dto.getUserCode());
            }

            // 学号全局重复检查（在事务外预检查）
            if (userService.lambdaQuery()
                    .eq(User::getUserCode, dto.getUserCode())
                    .exists()) {
                result.addError("学工号已存在: " + dto.getUserCode());
            }
        }

        return result;
    }

    private void saveData() {
        // 在事务中执行保存操作
        transactionTemplate.execute(status -> {
            try {
                // 1. 转换DTO为User实体
                List<User> users = cachedDTOList.stream()
                        .map(this::convertToUser)
                        .collect(Collectors.toList());

                // 2. 批量保存用户
                userService.saveBatch(users);

                // 3. 构建用户学号->用户ID映射
                Map<String, Long> userCodeIdMap = users.stream()
                        .collect(Collectors.toMap(User::getUserCode, User::getId));

                // 4. 构建角色关联关系
                List<RoleUser> roleUsers = new ArrayList<>();
                for (UserImportDTO dto : cachedDTOList) {
                    Long userId = userCodeIdMap.get(dto.getUserCode());
                    if (userId != null) {
                        Integer roleId = convertRole(dto.getRoleStr());
                        roleUsers.add(createRoleUser(roleId.longValue(), userId));
                    }
                }

                // 5. 批量保存角色关联
                if (!roleUsers.isEmpty()) {
                    roleUserService.saveBatch(roleUsers);
                }
                return true;
            } catch (Exception e) {
                status.setRollbackOnly();
                logger.error("导入用户事务失败", e);
                // 记录整个批次的错误
                for (UserImportDTO dto : cachedDTOList) {
                    errorList.add(new ImportResult(-1, "系统错误: " + e.getMessage()));
                }
                return false;
            }
        });
    }

    private User convertToUser(UserImportDTO dto) {
        User user = new User();
        user.setName(dto.getName());
        user.setGender(convertGender(dto.getGenderStr()));
        String userCode = dto.getUserCode();
        user.setUserCode(userCode);
        user.setPhone(dto.getPhone());
        user.setEmail(dto.getEmail());
        user.setCollege(convertCollege(dto.getCollegeStr()));
        user.setClassName(convertClassName(dto.getClassName()));
        user.setPosition(convertPosition(dto.getPositionStr()));
        user.setRole(convertRole(dto.getRoleStr()));
        // 系统字段
        user.setCreateUser(creator);
        user.setUpdateUser(creator);
        String encryptPwd = SecurityPasswordService.getEncryptPwd(userCode);
        user.setLoginPwd(encryptPwd); // 默认密码
        user.setStatus(EnumConverter.defaultStatus);
        user.setYn(EnumConverter.defaultYn);
        return user;
    }

    private RoleUser createRoleUser(Long roleId, Long userId) {
        RoleUser roleUser = new RoleUser();
        roleUser.setRoleId(roleId);
        roleUser.setUserId(userId);
        Date now = new Date();
        roleUser.setCreateTime(now);
        roleUser.setUpdateTime(now);
        return roleUser;
    }

    private Integer convertGender(String genderStr) {
        if (StringUtils.isBlank(genderStr)) {
            throw new RuntimeException("性别不能为空");
        }
        Integer genderCode = EnumConverter.convertSexNameToCode(genderStr);

        if (null == genderCode) {
            throw new RuntimeException("无效的性别名: " + genderStr);
        }
        return genderCode;
    }

    private String convertCollege(String collegeStr) {
        if (StringUtils.isBlank(collegeStr)) {
            throw new RuntimeException("学院不能为空");
        }
        String collegeName = EnumConverter.convertCollegeNameToCode(collegeStr);

        if (StringUtils.isBlank(collegeName)) {
            throw new RuntimeException("无效的学院名: " + collegeStr);
        }
        return collegeName;
    }

    private String convertClassName(String classNameStr) {
        if (StringUtils.isBlank(classNameStr)) {
            throw new RuntimeException("班级名不能为空");
        }
        String className = EnumConverter.convertClassNameToCode(classNameStr);

        if (StringUtils.isBlank(className)) {
            throw new RuntimeException("无效的班级名: " + classNameStr);
        }
        return className;
    }

    private Integer convertPosition(String positionStr) {
        if (StringUtils.isBlank(positionStr)) {
            throw new RuntimeException("职务不能为空");
        }
        switch (positionStr) {
            case "学生":
                return 0;
            case "老师":
                return 1;
            default:
                throw new RuntimeException("无效的职务类型: " + positionStr);
        }
    }

    private Integer convertRole(String roleStr) {
        if (StringUtils.isBlank(roleStr)) {
            throw new RuntimeException("角色值不能为空 ");
        }
        String roleCode;
        switch (roleStr) {
            case "管理员":
                roleCode = "admin";
                break;
            case "普通用户":
                roleCode = "student";
                break;
            default:
                throw new RuntimeException("无效的角色类型: " + roleStr);
        }

        Long roleId = roleService.getRoleIdByName(roleCode);
        if (roleId == null) {
            throw new RuntimeException("角色不存在: " + roleStr);
        }
        return roleId.intValue();
    }

    private void validateUser(UserImportDTO dto) {
        if (userService.lambdaQuery()
                .eq(User::getUserCode, dto.getUserCode())
                .exists()) {
            throw new RuntimeException("学工号已存在: " + dto.getUserCode());
        }
    }

    public List<ImportResult> getErrorList() {
        return errorList;
    }

    @Data
    @AllArgsConstructor
    public static class ImportResult {
        private Integer rowNum;
        private String message;
    }

    // 校验结果封装类
    private static class ValidationResult {
        private final List<String> errors = new ArrayList<>();

        public void addError(String error) {
            errors.add(error);
        }

        public boolean isValid() {
            return errors.isEmpty();
        }

        public String getErrorMessage() {
            return String.join("; ", errors);
        }
    }

    // 添加获取处理计数的方法
    public int getProcessedCount() {
        return processedCount;
    }

}